﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Net;
using System.ComponentModel;
using ArtMath.Resource;
using ArtMath.Attribute;
using ArtMath.Component.Annotation.Converter;
using ArtMath.Core.Helper;
using ArtMath.Setting;
using ArtMath.Core.Data;
using ArtMath.Helper;
using ArtMath.Component.CoordinateSystem;
using ArtMath.CommonType;

namespace ArtMath.Component.Annotation
{
    /// <summary>
    /// 图片
    /// </summary>
    [Serializable]
    public class Picture : CustomBase
    {
        public enum PictureSource
        {
            LocalPicture,
            NetworkPicture,
        }
        string sourceLocation;
        Image localImg, reversedLocalImg, localLightImg, netImg, reversedNetImg, netLightImg;
        PictureSource mode;
        //Color tranColor = Color.Transparent;
        public Picture(SketchPad pad, string name, bool addToList = true) : base(pad, name, ToolTypeName.tp, addToList)
        {

        }

        [MultilingualCategory("Structure"), MultilingualDisplayName(null, "Network", "Image")]
        public string WebImage
        {
            get { return sourceLocation; }
            set
            {
                try
                {
                    netImg = Image.FromStream(WebRequest.Create(value).GetResponse().GetResponseStream());
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, Resources.Translate("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                reversedNetImg = ReverseImage(netImg as Bitmap);
                netLightImg = LightImage(netImg as Bitmap);
                sourceLocation = value;
                Pad.Canvas.Invalidate();
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName(null, "Local", "Image")]
        public Image LocalImage
        {
            get { return localImg; }
            set
            {
                localImg = value;
                reversedLocalImg = ReverseImage(localImg as Bitmap);
                localLightImg = LightImage(localImg as Bitmap);
                Pad.Canvas.Invalidate();
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName(null, "Image", "Source"), TypeConverter(typeof(PictureSourceConverter))]
        public PictureSource ImageSource
        {
            get { return mode; }
            set
            {
                mode = value;
                Pad.Canvas.Invalidate();
            }
        }
        public override SizeF ActualSize
        {
            get
            {
                if (!FitSize)
                {
                    switch (ImageSource)
                    {
                        case PictureSource.LocalPicture:
                            return localImg.Size;
                        case PictureSource.NetworkPicture:
                            return netImg.Size;
                    }
                }
                return base.ActualSize;
            }
        }
        //[Browsable(false)]
        //public Color TransparentColor
        //{
        //    get { return tranColor; }
        //    set
        //    {
        //        tranColor = value;
        //        if (localImg != null) setTransparentColor(localImg as Bitmap);
        //        if (reversedLocalImg != null) setTransparentColor(reversedLocalImg as Bitmap);
        //        if (netImg != null) setTransparentColor(netImg as Bitmap);
        //        if (reversedNetImg != null) setTransparentColor(reversedNetImg as Bitmap);
        //    }
        //}
        //void setTransparentColor(Bitmap bmp)
        //{
        //    for (int y = 0; y < bmp.Height; y++)
        //    {
        //        for (int x = 0; x < bmp.Width; x++)
        //        {
        //            if (bmp.GetPixel(x, y) == TransparentColor)
        //            {
        //                bmp.SetPixel(x, y, Color.Transparent);
        //            }
        //        }
        //    }
        //}
        Image LightImage(Bitmap srcImg)
        {
            Bitmap bmp = new Bitmap(srcImg.Width, srcImg.Height);
            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    bmp.SetPixel(x, y, srcImg.GetPixel(x, y).HSVOffset(0, Settings.Instance.TransformSaturationOffset, 0));
                }
            }
            return bmp;
        }
        Image ReverseImage(Bitmap srcImg)
        {
            //Bitmap bmp = new Bitmap(sourceImage.Width, sourceImage.Height);
            ////frmProgress pro = new frmProgress("正在生成反色图片...", bmp.Width * bmp.Height,
            ////    (BackgroundWorker bgw) =>
            ////    {
            //Dictionary<Color, Color> revColors = new Dictionary<Color, Color>();
            //Color origin, rev;
            //for (int y = 0; y < bmp.Height; y++)
            //{
            //    for (int x = 0; x < bmp.Width; x++)
            //    {
            //        origin = sourceImage.GetPixel(x, y);
            //        if (!revColors.TryGetValue(origin, out rev))
            //        {
            //            rev = origin.GetReversedColor(false);
            //            revColors.Add(origin, rev);
            //        }
            //        bmp.SetPixel(x, y, rev);
            //        //bgw.ReportProgress(0);
            //    }
            //}
            ////    });
            ////pro.ShowDialog();
            //return bmp;
            Bitmap bmp = new Bitmap(srcImg.Width, srcImg.Height);
            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    bmp.SetPixel(x, y, srcImg.GetPixel(x, y).GetReversedColor(false));
                }
            }
            return bmp;
        }

        public override void Paint(Graphics gra)
        {
            if (ObjectState == ObjectState.Normal && Visible)
            {
                gra.Transform(Pxy, Settings.Instance.SelfRotate ? -RotateAngle.DegreeValue : -selfRotateAngle * Core.Helper.Angle.RToD, () =>
                {
                    RectangleF rect = new RectangleF(new PointF(0, 0), ActualSize);
                    switch (ImageSource)
                    {
                        case PictureSource.LocalPicture:
                            if (localImg != null && reversedLocalImg != null)
                            {
                                gra.DrawImage(StyleState_ == StyleState.Hover || Selected && Pad.UseReversedColor ? reversedLocalImg : localImg, rect);
                            }
                            break;
                        case PictureSource.NetworkPicture:
                            if (netImg != null && reversedNetImg != null)
                            {
                                gra.DrawImage(StyleState_ == StyleState.Hover || Selected && Pad.UseReversedColor ? reversedNetImg : netImg, rect);
                            }
                            break;
                    }
                });
            }
            base.Paint(gra);
        }
        public override void PaintLight(Graphics gra)
        {
            RectangleF rect = new RectangleF(new PointF(0, 0), ActualSize);
            switch (ImageSource)
            {
                case PictureSource.LocalPicture:
                    if (localLightImg != null)
                    {
                        gra.DrawImage(localLightImg, rect);
                    }
                    break;
                case PictureSource.NetworkPicture:
                    if (netLightImg != null)
                    {
                        gra.DrawImage(netLightImg, rect);
                    }
                    break;
            }
            base.PaintLight(gra);
        }
        public override Base CreateMirrorImage(double A, double B, double C)
        {
            return base.CreateMirrorImage(A, B, C);
        }
        public override void CreateComponents()
        {
            Location.SetFromPointD(Pad.PxyToMath(SpareCoordinate_));
            if (UIInteraction.ObjectArguments.CommonValue.StartsWith("http", StringComparison.OrdinalIgnoreCase))
            {
                WebImage = UIInteraction.ObjectArguments.CommonValue;
                ImageSource = PictureSource.NetworkPicture;
            }
            else
            {
                try
                {
                    LocalImage = Image.FromFile(UIInteraction.ObjectArguments.CommonValue);
                    ImageSource = PictureSource.LocalPicture;
                }
                catch (Exception ex)
                {
                    Pad.ShowMessage(ex.Message, MessageType.Error);
                }
            }
            if (!FitSize)
            {
                switch (ImageSource)
                {
                    case PictureSource.LocalPicture:
                        Size.SetFromSizeD(localImg.Width, localImg.Height);
                        break;
                    case PictureSource.NetworkPicture:
                        Size.SetFromSizeD(netImg.Width, netImg.Height);
                        break;
                }
            }
            base.CreateComponents();
        }
        public override object GetCopyInfo()
        {
            return Tuple.Create(Location.ToPointD(), sourceLocation, new object[] { localImg?.Clone(), reversedLocalImg?.Clone(), localLightImg?.Clone(), netImg?.Clone(), reversedNetImg?.Clone(), netLightImg?.Clone() }, mode);
        }
        public override void AutoCreate(object createInfo, bool tryOffset = false)
        {
            Tuple<PointD, string, object[], PictureSource> info = createInfo as Tuple<PointD, string, object[], PictureSource>;
            if (info == null) return;
            PointD[] tmp = new PointD[] { info.Item1 };
            if (tryOffset)
            {
                Pad.CopyOffset(ToolType, tmp);
            }
            PolarCoordinate pc = Pad.Coordinate as PolarCoordinate;
            Location.SetFromPointD(pc != null ? pc.XYtoRT(tmp[0]) : tmp[0]);
            sourceLocation = info.Item2;
            localImg = info.Item3[0] as Image;
            reversedLocalImg = info.Item3[1] as Image;
            localLightImg = info.Item3[2] as Image;
            netImg = info.Item3[3] as Image;
            reversedNetImg = info.Item3[4] as Image;
            netLightImg = info.Item3[5] as Image;
            mode = info.Item4;
            base.CreateComponents();
        }
    }
}
